View Javadoc

1   // ReflectionImpl.java, created Sat Dec 14  2:52:34 2002 by mcmartin
2   // Copyright (C) 2001-3 John Whaley <jwhaley@alum.mit.edu>
3   // Licensed under the terms of the GNU LGPL; see COPYING for details.
4   package joeq.Runtime;
5   
6   import java.util.Set;
7   import java.lang.reflect.Array;
8   import java.lang.reflect.Constructor;
9   import java.lang.reflect.Field;
10  import java.lang.reflect.InvocationTargetException;
11  import java.lang.reflect.Member;
12  import java.lang.reflect.Method;
13  import java.lang.reflect.Modifier;
14  import joeq.Class.PrimordialClassLoader;
15  import joeq.Class.jq_Class;
16  import joeq.Class.jq_ClassInitializer;
17  import joeq.Class.jq_Field;
18  import joeq.Class.jq_Initializer;
19  import joeq.Class.jq_InstanceField;
20  import joeq.Class.jq_InstanceMethod;
21  import joeq.Class.jq_Member;
22  import joeq.Class.jq_Method;
23  import joeq.Class.jq_NameAndDesc;
24  import joeq.Class.jq_Primitive;
25  import joeq.Class.jq_Reference;
26  import joeq.Class.jq_StaticField;
27  import joeq.Class.jq_StaticMethod;
28  import joeq.Class.jq_Type;
29  import joeq.ClassLib.ClassLibInterface;
30  import joeq.Main.jq;
31  import joeq.Memory.Address;
32  import joeq.Memory.HeapAddress;
33  import joeq.UTF.Utf8;
34  import jwutil.util.Assert;
35  import jwutil.util.Convert;
36  
37  /***
38   * @author  John Whaley <jwhaley@alum.mit.edu>
39   * @version $Id: ReflectionImpl.java 2242 2005-03-21 12:39:42Z joewhaley $
40   */
41  public class ReflectionImpl implements Reflection.Delegate {
42  
43      public static boolean REPORT_JDK_ERRORS = false;
44      
45      public final jq_Reference getTypeOf(Object o) {
46          if (jq.RunningNative) return jq_Reference.getTypeOf(o);
47          return (jq_Reference) getJQType(o.getClass());
48      }
49      
50      // Map between our jq_Type objects and JDK Class objects
51      public final jq_Type getJQType(Class c) {
52          if (jq.RunningNative) return ClassLibInterface.DEFAULT.getJQType(c);
53          //if (c == null) return null;
54          if (c.isPrimitive()) {
55              if (c == Byte.TYPE) return jq_Primitive.BYTE;
56              if (c == Character.TYPE) return jq_Primitive.CHAR;
57              if (c == Double.TYPE) return jq_Primitive.DOUBLE;
58              if (c == Float.TYPE) return jq_Primitive.FLOAT;
59              if (c == Integer.TYPE) return jq_Primitive.INT;
60              if (c == Long.TYPE) return jq_Primitive.LONG;
61              if (c == Short.TYPE) return jq_Primitive.SHORT;
62              if (c == Boolean.TYPE) return jq_Primitive.BOOLEAN;
63              if (c == Void.TYPE) return jq_Primitive.VOID;
64              Assert.UNREACHABLE(c.toString());
65              return null;
66          }
67          String className = c.getName().replace('.','/');
68          if (!className.startsWith("[")) className = "L"+className+";";
69          className = joeq.ClassLib.ClassLibInterface.convertClassLibDesc(className);
70          return PrimordialClassLoader.loader.getOrCreateBSType(className);
71      }
72      public final Class getJDKType(jq_Type c) {
73          if (jq.RunningNative) return c.getJavaLangClassObject();
74          //if (c == null) return null;
75          if (c.getJavaLangClassObject() != null)
76              return c.getJavaLangClassObject();
77          if (c.isPrimitiveType()) 
78              return getJDKType((jq_Primitive)c);
79          else
80              return getJDKType((jq_Reference)c);
81      }
82      public final Class getJDKType(jq_Primitive c) {
83          if (jq.RunningNative) return c.getJavaLangClassObject();
84          if (c.getJavaLangClassObject() != null)
85              return c.getJavaLangClassObject();
86          // cannot compare to jq_Primitive types here, as they may not
87          // have been initialized yet.  so we compare descriptors instead.
88          if (c.getDesc() == Utf8.BYTE_DESC) return Byte.TYPE;
89          if (c.getDesc() == Utf8.CHAR_DESC) return Character.TYPE;
90          if (c.getDesc() == Utf8.DOUBLE_DESC) return Double.TYPE;
91          if (c.getDesc() == Utf8.FLOAT_DESC) return Float.TYPE;
92          if (c.getDesc() == Utf8.INT_DESC) return Integer.TYPE;
93          if (c.getDesc() == Utf8.LONG_DESC) return Long.TYPE;
94          if (c.getDesc() == Utf8.SHORT_DESC) return Short.TYPE;
95          if (c.getDesc() == Utf8.BOOLEAN_DESC) return Boolean.TYPE;
96          if (c.getDesc() == Utf8.VOID_DESC) return Void.TYPE;
97          Assert.UNREACHABLE(c.getName());
98          return null;
99      }
100     public Class getJDKType(jq_Reference c) {
101         if (jq.RunningNative) return c.getJavaLangClassObject();
102         //if (c == null) return null;
103         if (c.getJavaLangClassObject() != null)
104             return c.getJavaLangClassObject();
105         try {
106             return Class.forName(c.getJDKName(), false, Reflection.class.getClassLoader());
107             //return Class.forName(c.getJDKName(), false, c.getClassLoader());
108         } catch (ClassNotFoundException x) {
109             if (!c.getJDKName().startsWith("joeq.ClassLib") && !c.getJDKName().startsWith("L&"))
110                 SystemInterface.debugwriteln("Note: "+c.getJDKName()+" was not found in host jdk");
111             return null;
112         }
113     }
114     
115     // Map between our jq_Member objects and JDK Member objects
116     public final jq_Field getJQMember(Field f) {
117         if (jq.RunningNative) return ClassLibInterface.DEFAULT.getJQField(f);
118         jq_Class c = (jq_Class)getJQType(f.getDeclaringClass());
119         //if (c == null) return null;
120         jq_NameAndDesc nd = new jq_NameAndDesc(Utf8.get(f.getName()), getJQType(f.getType()).getDesc());
121         nd = joeq.ClassLib.ClassLibInterface.convertClassLibNameAndDesc(c, nd);
122         jq_Field m = (jq_Field)c.getDeclaredMember(nd);
123         if (m == null) {
124             if (!Utf8.NO_NEW) {
125                 //SystemInterface.debugwriteln("Reference to jdk field "+f.toString()+" does not exist, creating "+c+"."+nd);
126                 if (Modifier.isStatic(f.getModifiers()))
127                     m = c.getOrCreateStaticField(nd);
128                 else
129                     m = c.getOrCreateInstanceField(nd);
130             }
131         }
132         return m;
133     }
134     public final jq_Method getJQMember(Method f) {
135         if (jq.RunningNative) return ClassLibInterface.DEFAULT.getJQMethod(f);
136         jq_Class c = (jq_Class)getJQType(f.getDeclaringClass());
137         //if (c == null) return null;
138         StringBuffer desc = new StringBuffer();
139         desc.append('(');
140         Class[] param_types = f.getParameterTypes();
141         for (int i=0; i<param_types.length; ++i) {
142             desc.append(getJQType(param_types[i]).getDesc().toString());
143         }
144         desc.append(')');
145         desc.append(getJQType(f.getReturnType()).getDesc().toString());
146         jq_NameAndDesc nd = new jq_NameAndDesc(Utf8.get(f.getName()), Utf8.get(desc.toString()));
147         nd = joeq.ClassLib.ClassLibInterface.convertClassLibNameAndDesc(c, nd);
148         jq_Method m = (jq_Method)c.getDeclaredMember(nd);
149         if (m == null) {
150             if (!Utf8.NO_NEW) {
151                 //SystemInterface.debugwriteln("Reference to jdk method "+f.toString()+" does not exist, creating "+c+"."+nd);
152                 if (Modifier.isStatic(f.getModifiers()))
153                     m = c.getOrCreateStaticMethod(nd);
154                 else
155                     m = c.getOrCreateInstanceMethod(nd);
156             }
157         }
158         return m;
159     }
160     public final jq_Initializer getJQMember(Constructor f) {
161         if (jq.RunningNative) return ClassLibInterface.DEFAULT.getJQInitializer(f);
162         jq_Class c = (jq_Class)getJQType(f.getDeclaringClass());
163         //if (c == null) return null;
164         StringBuffer desc = new StringBuffer();
165         desc.append('(');
166         Class[] param_types = f.getParameterTypes();
167         for (int i=0; i<param_types.length; ++i) {
168             desc.append(getJQType(param_types[i]).getDesc().toString());
169         }
170         desc.append(")V");
171         jq_NameAndDesc nd = new jq_NameAndDesc(Utf8.get("<init>"), Utf8.get(desc.toString()));
172         nd = joeq.ClassLib.ClassLibInterface.convertClassLibNameAndDesc(c, nd);
173         jq_Initializer m = (jq_Initializer)c.getDeclaredMember(nd);
174         if (m == null) {
175             if (!Utf8.NO_NEW) {
176                 //SystemInterface.debugwriteln("Reference to jdk constructor "+f.toString()+" does not exist, creating "+c+"."+nd);
177                 m = (jq_Initializer)c.getOrCreateInstanceMethod(nd);
178             }
179         }
180         return m;
181     }
182     public boolean USE_DECLARED_FIELDS_CACHE = true;
183     private static java.util.HashMap declaredFieldsCache;
184     public final Field getJDKField(Class c, String name) {
185         Field[] fields = null;
186         if (USE_DECLARED_FIELDS_CACHE) {
187             if (declaredFieldsCache == null) declaredFieldsCache = new java.util.HashMap();
188             else fields = (Field[])declaredFieldsCache.get(c);
189             if (fields == null) {
190                 try {
191                     fields = c.getDeclaredFields();
192                 } catch (NoClassDefFoundError x) {
193                     if (REPORT_JDK_ERRORS) SystemInterface.debugwriteln("Note: "+c+" could not be loaded in host jdk");
194                     return null;
195                 }
196                 declaredFieldsCache.put(c, fields);
197             }
198         } else {
199             try {
200                 fields = c.getDeclaredFields();
201             } catch (NoClassDefFoundError x) {
202                 if (REPORT_JDK_ERRORS) SystemInterface.debugwriteln("Note: "+c+" could not be loaded in host jdk");
203                 return null;
204             }
205         }
206         for (int i=0; i<fields.length; ++i) {
207             Field f2 = fields[i];
208             if (f2.getName().equals(name)) {
209                 //f2.setAccessible(true);
210                 return f2;
211             }
212         }
213         //jq.UNREACHABLE(c+"."+name);
214         return null;
215     }
216     public boolean USE_DECLARED_METHODS_CACHE = true;
217     private static java.util.HashMap declaredMethodsCache;
218     public final Method getJDKMethod(Class c, String name, Class[] args) {
219         Method[] methods = null;
220         if (USE_DECLARED_METHODS_CACHE) {
221             if (declaredMethodsCache == null) declaredMethodsCache = new java.util.HashMap();
222             else methods = (Method[])declaredMethodsCache.get(c);
223             if (methods == null) {
224                 try {
225                     methods = c.getDeclaredMethods();
226                 } catch (NoClassDefFoundError x) {
227                     if (REPORT_JDK_ERRORS) SystemInterface.debugwriteln("Note: "+c+" could not be loaded in host jdk");
228                     return null;
229                 }
230                 declaredMethodsCache.put(c, methods);
231             }
232         } else {
233             try {
234                 methods = c.getDeclaredMethods();
235             } catch (NoClassDefFoundError x) {
236                 if (REPORT_JDK_ERRORS) SystemInterface.debugwriteln("Note: "+c+" could not be loaded in host jdk");
237                 return null;
238             }
239         }
240 uphere:
241         for (int i=0; i<methods.length; ++i) {
242             Method f2 = methods[i];
243             if (f2.getName().equals(name)) {
244                 Class[] args2 = f2.getParameterTypes();
245                 if (args.length != args2.length) continue uphere;
246                 for (int j=0; j<args.length; ++j) {
247                     if (!args[j].equals(args2[j])) continue uphere;
248                 }
249                 //f2.setAccessible(true);
250                 return f2;
251             }
252         }
253         //jq.UNREACHABLE(c+"."+name+" "+args);
254         return null;
255     }
256     public final Constructor getJDKConstructor(Class c, Class[] args) {
257         Constructor[] consts;
258         try {
259             consts = c.getDeclaredConstructors();
260         } catch (NoClassDefFoundError x) {
261             if (REPORT_JDK_ERRORS) SystemInterface.debugwriteln("Note: "+c+" could not be loaded in host jdk");
262             return null;
263         }
264 uphere:
265         for (int i=0; i<consts.length; ++i) {
266             Constructor f2 = consts[i];
267             Class[] args2 = f2.getParameterTypes();
268             if (args.length != args2.length) continue uphere;
269             for (int j=0; j<args.length; ++j) {
270                 if (!args[j].equals(args2[j])) continue uphere;
271             }
272             //f2.setAccessible(true);
273             return f2;
274         }
275         //jq.UNREACHABLE(c+".<init> "+args);
276         return null;
277     }
278     public final Member getJDKMember(jq_Member m) {
279         if (jq.RunningNative) return m.getJavaLangReflectMemberObject();
280         if (m.getJavaLangReflectMemberObject() != null)
281             return m.getJavaLangReflectMemberObject();
282         Class c = getJDKType(m.getDeclaringClass());
283         if (m instanceof jq_Field) {
284             Member ret = getJDKField(c, m.getName().toString());
285             if (ret == null) {
286                 // TODO: a synthetic field, so there is no java.lang.reflect.Field object yet.
287             }
288             return ret;
289         } else if (m instanceof jq_Initializer) {
290             jq_Initializer m2 = (jq_Initializer)m;
291             jq_Type[] param_types = m2.getParamTypes();
292             int num_of_args = param_types.length-1; // -1 for this ptr
293             Class[] args = new Class[num_of_args];
294             for (int i=0; i<num_of_args; ++i) {
295                 args[i] = getJDKType(param_types[i+1]);
296             }
297             Member ret = getJDKConstructor(c, args);
298             if (ret == null) {
299                 // TODO: a synthetic field, so there is no java.lang.reflect.Field object yet.
300             }
301             return ret;
302         } else if (m instanceof jq_ClassInitializer) {
303             return null; // <clinit> methods have no Method object
304         } else {
305             Assert._assert(m instanceof jq_Method);
306             jq_Method m2 = (jq_Method)m;
307             int offset = m2.isStatic()?0:1;
308             jq_Type[] param_types = m2.getParamTypes();
309             int num_of_args = param_types.length-offset;
310             Class[] args = new Class[num_of_args];
311             for (int i=0; i<num_of_args; ++i) {
312                 args[i] = getJDKType(param_types[i+offset]);
313             }
314             Member ret = getJDKMethod(c, m.getName().toString(), args);
315             if (ret == null) {
316                 // TODO: a synthetic field, so there is no java.lang.reflect.Field object yet.
317             }
318             return ret;
319         }
320     }
321     
322     // reflective invocations.
323     public void invokestatic_V(jq_StaticMethod m) throws Throwable {
324         if (jq.RunningNative) {
325             Assert._assert(m.getDeclaringClass().isClsInitRunning());
326             Unsafe.invoke(m.getDefaultCompiledVersion().getEntrypoint());
327             return;
328         } else {
329             Assert.UNREACHABLE();
330         }
331     }
332     public int invokestatic_I(jq_StaticMethod m) throws Throwable {
333         if (jq.RunningNative) {
334             Assert._assert(m.getDeclaringClass().isClsInitRunning());
335             return (int)Unsafe.invoke(m.getDefaultCompiledVersion().getEntrypoint());
336         } else {
337             Assert.UNREACHABLE();
338             return 0;
339         }
340     }
341     public Object invokestatic_A(jq_StaticMethod m) throws Throwable {
342         if (jq.RunningNative) {
343             Assert._assert(m.getDeclaringClass().isClsInitRunning());
344             return ((HeapAddress)Unsafe.invokeA(m.getDefaultCompiledVersion().getEntrypoint())).asObject();
345         } else {
346             Assert.UNREACHABLE();
347             return null;
348         }
349     }
350     public long invokestatic_J(jq_StaticMethod m) throws Throwable {
351         if (jq.RunningNative) {
352             Assert._assert(m.getDeclaringClass().isClsInitRunning());
353             return Unsafe.invoke(m.getDefaultCompiledVersion().getEntrypoint());
354         } else {
355             Assert.UNREACHABLE();
356             return 0L;
357         }
358     }
359     public void invokestatic_V(jq_StaticMethod m, Object arg1) throws Throwable {
360         if (jq.RunningNative) {
361             Assert._assert(m.getDeclaringClass().isClsInitRunning());
362             Unsafe.pushArgA(HeapAddress.addressOf(arg1));
363             Unsafe.invoke(m.getDefaultCompiledVersion().getEntrypoint());
364             return;
365         } else {
366             Assert.UNREACHABLE();
367             return;
368         }
369     }
370     public void invokeinstance_V(jq_InstanceMethod m, Object dis) throws Throwable {
371         Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(dis), m.getDeclaringClass()));
372         if (jq.RunningNative) {
373             Assert._assert(m.getDeclaringClass().isClsInitRunning());
374             Unsafe.pushArgA(HeapAddress.addressOf(dis));
375             Unsafe.invoke(m.getDefaultCompiledVersion().getEntrypoint());
376         } else {
377             Assert.UNREACHABLE();
378             return;
379         }
380     }
381     public Object invokeinstance_A(jq_InstanceMethod m, Object dis) throws Throwable {
382         Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(dis), m.getDeclaringClass()));
383         if (jq.RunningNative) {
384             Assert._assert(m.getDeclaringClass().isClsInitRunning());
385             Unsafe.pushArgA(HeapAddress.addressOf(dis));
386             return ((HeapAddress)Unsafe.invokeA(m.getDefaultCompiledVersion().getEntrypoint())).asObject();
387         } else {
388             Assert.UNREACHABLE();
389             return null;
390         }
391     }
392     public void invokeinstance_V(jq_InstanceMethod m, Object dis, Object arg1) throws Throwable {
393         Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(dis), m.getDeclaringClass()));
394         if (jq.RunningNative) {
395             Assert._assert(m.getDeclaringClass().isClsInitRunning());
396             Unsafe.pushArgA(HeapAddress.addressOf(dis));
397             Unsafe.pushArgA(HeapAddress.addressOf(arg1));
398             Unsafe.invoke(m.getDefaultCompiledVersion().getEntrypoint());
399             return;
400         } else {
401             Assert.UNREACHABLE();
402             return;
403         }
404     }
405     public Object invokeinstance_A(jq_InstanceMethod m, Object dis, Object arg1) throws Throwable {
406         Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(dis), m.getDeclaringClass()));
407         if (jq.RunningNative) {
408             Assert._assert(m.getDeclaringClass().isClsInitRunning());
409             Unsafe.pushArgA(HeapAddress.addressOf(dis));
410             Unsafe.pushArgA(HeapAddress.addressOf(arg1));
411             return ((HeapAddress)Unsafe.invokeA(m.getDefaultCompiledVersion().getEntrypoint())).asObject();
412         } else {
413             Assert.UNREACHABLE();
414             return null;
415         }
416     }
417     public boolean invokeinstance_Z(jq_InstanceMethod m, Object dis, Object arg1) throws Throwable {
418         Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(dis), m.getDeclaringClass()));
419         if (jq.RunningNative) {
420             Assert._assert(m.getDeclaringClass().isClsInitRunning());
421             Unsafe.pushArgA(HeapAddress.addressOf(dis));
422             Unsafe.pushArgA(HeapAddress.addressOf(arg1));
423             return ((int)Unsafe.invoke(m.getDefaultCompiledVersion().getEntrypoint())) != 0;
424         } else {
425             Assert.UNREACHABLE();
426             return false;
427         }
428     }
429     public void invokeinstance_V(jq_InstanceMethod m, Object dis, Object arg1, Object arg2) throws Throwable {
430         Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(dis), m.getDeclaringClass()));
431         if (jq.RunningNative) {
432             Assert._assert(m.getDeclaringClass().isClsInitRunning());
433             Unsafe.pushArgA(HeapAddress.addressOf(dis));
434             Unsafe.pushArgA(HeapAddress.addressOf(arg1));
435             Unsafe.pushArgA(HeapAddress.addressOf(arg2));
436             Unsafe.invoke(m.getDefaultCompiledVersion().getEntrypoint());
437             return;
438         } else {
439             Assert.UNREACHABLE();
440             return;
441         }
442     }
443     public void invokeinstance_V(jq_InstanceMethod m, Object dis, Object arg1, Object arg2, Object arg3) throws Throwable {
444         Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(dis), m.getDeclaringClass()));
445         if (jq.RunningNative) {
446             Assert._assert(m.getDeclaringClass().isClsInitRunning());
447             Unsafe.pushArgA(HeapAddress.addressOf(dis));
448             Unsafe.pushArgA(HeapAddress.addressOf(arg1));
449             Unsafe.pushArgA(HeapAddress.addressOf(arg2));
450             Unsafe.pushArgA(HeapAddress.addressOf(arg3));
451             Unsafe.invoke(m.getDefaultCompiledVersion().getEntrypoint());
452             return;
453         } else {
454             Assert.UNREACHABLE();
455             return;
456         }
457     }
458     public void invokeinstance_V(jq_InstanceMethod m, Object dis, Object arg1, Object arg2, Object arg3, long arg4) throws Throwable {
459         Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(dis), m.getDeclaringClass()));
460         if (jq.RunningNative) {
461             Assert._assert(m.getDeclaringClass().isClsInitRunning());
462             Unsafe.pushArgA(HeapAddress.addressOf(dis));
463             Unsafe.pushArgA(HeapAddress.addressOf(arg1));
464             Unsafe.pushArgA(HeapAddress.addressOf(arg2));
465             Unsafe.pushArgA(HeapAddress.addressOf(arg3));
466             Unsafe.pushArg((int)(arg4 >> 32)); // hi
467             Unsafe.pushArg((int)arg4);         // lo
468             Unsafe.invoke(m.getDefaultCompiledVersion().getEntrypoint());
469             return;
470         } else {
471             Assert.UNREACHABLE();
472             return;
473         }
474     }
475     public void invokeinstance_V(jq_InstanceMethod m, Object dis, Object arg1, int arg2, long arg3, int arg4) throws Throwable {
476         Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(dis), m.getDeclaringClass()));
477         if (jq.RunningNative) {
478             Assert._assert(m.getDeclaringClass().isClsInitRunning());
479             Unsafe.pushArgA(HeapAddress.addressOf(dis));
480             Unsafe.pushArgA(HeapAddress.addressOf(arg1));
481             Unsafe.pushArg(arg2);
482             Unsafe.pushArg((int)(arg3 >> 32)); // hi
483             Unsafe.pushArg((int)arg3);         // lo
484             Unsafe.pushArg(arg4);
485             Unsafe.invoke(m.getDefaultCompiledVersion().getEntrypoint());
486             return;
487         } else {
488             Assert.UNREACHABLE();
489             return;
490         }
491     }
492     public long invoke(jq_Method m, Object dis, Object[] args)
493         throws IllegalArgumentException, InvocationTargetException
494     {
495         jq_Type[] params = m.getParamTypes();
496         int offset;
497         if (dis != null) {
498             Assert._assert(!m.isStatic());
499             Unsafe.pushArgA(HeapAddress.addressOf(dis));
500             offset = 1;
501         } else {
502             offset = 0;
503         }
504         if (args != null) {
505             Assert._assert(params.length == args.length+offset);
506             for (int i=0; i<args.length; ++i) {
507                 jq_Type c = params[i+offset];
508                 if (c.isAddressType()) {
509                     Assert.TODO();
510                 } else if (c.isReferenceType()) {
511                     if (args[i] != null && !TypeCheck.isAssignable(jq_Reference.getTypeOf(args[i]), c))
512                         throw new IllegalArgumentException(args[i].getClass()+" is not assignable to "+c);
513                     Unsafe.pushArgA(HeapAddress.addressOf(args[i]));
514                 } else {
515                     if (c == jq_Primitive.BYTE) {
516                         int v = (int)Convert.unwrapToByte(args[i]);
517                         Unsafe.pushArg(v);
518                     } else if (c == jq_Primitive.CHAR) {
519                         int v = (int)Convert.unwrapToChar(args[i]);
520                         Unsafe.pushArg(v);
521                     } else if (c == jq_Primitive.DOUBLE) {
522                         long v = Double.doubleToRawLongBits(Convert.unwrapToDouble(args[i]));
523                         Unsafe.pushArg((int)(v >> 32)); // hi
524                         Unsafe.pushArg((int)v);         // lo
525                     } else if (c == jq_Primitive.FLOAT) {
526                         int v = Float.floatToRawIntBits(Convert.unwrapToFloat(args[i]));
527                         Unsafe.pushArg(v);
528                     } else if (c == jq_Primitive.INT) {
529                         int v = Convert.unwrapToInt(args[i]);
530                         Unsafe.pushArg(v);
531                     } else if (c == jq_Primitive.LONG) {
532                         long v = Convert.unwrapToLong(args[i]);
533                         Unsafe.pushArg((int)(v >> 32)); // hi
534                         Unsafe.pushArg((int)v);         // lo
535                     } else if (c == jq_Primitive.SHORT) {
536                         int v = (int)Convert.unwrapToShort(args[i]);
537                         Unsafe.pushArg(v);
538                     } else if (c == jq_Primitive.BOOLEAN) {
539                         int v = Convert.unwrapToBoolean(args[i])?1:0;
540                         Unsafe.pushArg(v);
541                     } else Assert.UNREACHABLE(c.toString());
542                 }
543             }
544         } else {
545             Assert._assert(params.length == offset);
546         }
547         try {
548             return Unsafe.invoke(m.getDefaultCompiledVersion().getEntrypoint());
549         } catch (Throwable t) {
550             throw new InvocationTargetException(t);
551         }
552     }
553     public Address invokeA(jq_Method m, Object dis, Object[] args)
554         throws IllegalArgumentException, InvocationTargetException
555     {
556         jq_Type[] params = m.getParamTypes();
557         int offset;
558         if (dis != null) {
559             Assert._assert(!m.isStatic());
560             Unsafe.pushArgA(HeapAddress.addressOf(dis));
561             offset = 1;
562         } else {
563             offset = 0;
564         }
565         if (args != null) {
566             Assert._assert(params.length == args.length+offset);
567             for (int i=0; i<args.length; ++i) {
568                 jq_Type c = params[i+offset];
569                 if (c.isAddressType()) {
570                     Assert.TODO();
571                 } else if (c.isReferenceType()) {
572                     if (args[i] != null && !TypeCheck.isAssignable(jq_Reference.getTypeOf(args[i]), c))
573                         throw new IllegalArgumentException(args[i].getClass()+" is not assignable to "+c);
574                     Unsafe.pushArgA(HeapAddress.addressOf(args[i]));
575                 } else {
576                     if (c == jq_Primitive.BYTE) {
577                         int v = (int)Convert.unwrapToByte(args[i]);
578                         Unsafe.pushArg(v);
579                     } else if (c == jq_Primitive.CHAR) {
580                         int v = (int)Convert.unwrapToChar(args[i]);
581                         Unsafe.pushArg(v);
582                     } else if (c == jq_Primitive.DOUBLE) {
583                         long v = Double.doubleToRawLongBits(Convert.unwrapToDouble(args[i]));
584                         Unsafe.pushArg((int)(v >> 32)); // hi
585                         Unsafe.pushArg((int)v);         // lo
586                     } else if (c == jq_Primitive.FLOAT) {
587                         int v = Float.floatToRawIntBits(Convert.unwrapToFloat(args[i]));
588                         Unsafe.pushArg(v);
589                     } else if (c == jq_Primitive.INT) {
590                         int v = Convert.unwrapToInt(args[i]);
591                         Unsafe.pushArg(v);
592                     } else if (c == jq_Primitive.LONG) {
593                         long v = Convert.unwrapToLong(args[i]);
594                         Unsafe.pushArg((int)(v >> 32)); // hi
595                         Unsafe.pushArg((int)v);         // lo
596                     } else if (c == jq_Primitive.SHORT) {
597                         int v = (int)Convert.unwrapToShort(args[i]);
598                         Unsafe.pushArg(v);
599                     } else if (c == jq_Primitive.BOOLEAN) {
600                         int v = Convert.unwrapToBoolean(args[i])?1:0;
601                         Unsafe.pushArg(v);
602                     } else Assert.UNREACHABLE(c.toString());
603                 }
604             }
605         } else {
606             Assert._assert(params.length == offset);
607         }
608         try {
609             return Unsafe.invokeA(m.getDefaultCompiledVersion().getEntrypoint());
610         } catch (Throwable t) {
611             throw new InvocationTargetException(t);
612         }
613     }
614     
615     public int getfield_I(Object o, jq_InstanceField f) {
616         Assert._assert(f.getType() == jq_Primitive.INT || f.getType() == jq_Primitive.FLOAT);
617         if (!jq.RunningNative) {
618             Object q = Reflection.obj_trav.getInstanceFieldValue(o, f);
619             if (q == null) return 0;
620             return ((Integer)q).intValue();
621         }
622         Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
623         return HeapAddress.addressOf(o).offset(f.getOffset()).peek4();
624     }
625     public long getfield_L(Object o, jq_InstanceField f) {
626         Assert._assert(f.getType() == jq_Primitive.LONG || f.getType() == jq_Primitive.DOUBLE);
627         if (!jq.RunningNative) {
628             Object q = Reflection.obj_trav.getInstanceFieldValue(o, f);
629             if (q == null) return 0L;
630             return ((Long)q).longValue();
631         }
632         Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
633         return HeapAddress.addressOf(o).offset(f.getOffset()).peek8();
634     }
635     public float getfield_F(Object o, jq_InstanceField f) {
636         Assert._assert(f.getType() == jq_Primitive.FLOAT);
637         if (!jq.RunningNative) {
638             Object q = Reflection.obj_trav.getInstanceFieldValue(o, f);
639             if (q == null) return 0f;
640             return ((Float)q).floatValue();
641         }
642         Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
643         return Float.intBitsToFloat(getfield_I(o, f));
644     }
645     public double getfield_D(Object o, jq_InstanceField f) {
646         Assert._assert(f.getType() == jq_Primitive.DOUBLE);
647         if (!jq.RunningNative) {
648             Object q = Reflection.obj_trav.getInstanceFieldValue(o, f);
649             if (q == null) return 0.;
650             return ((Double)q).doubleValue();
651         }
652         Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
653         return Double.longBitsToDouble(getfield_L(o, f));
654     }
655     public Object getfield_A(Object o, jq_InstanceField f) {
656         Assert._assert(f.getType().isReferenceType());
657         Assert._assert(!f.getType().isAddressType());
658         if (!jq.RunningNative) return Reflection.obj_trav.getInstanceFieldValue(o, f);
659         Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
660         return ((HeapAddress) HeapAddress.addressOf(o).offset(f.getOffset()).peek()).asObject();
661     }
662     public Address getfield_P(Object o, jq_InstanceField f) {
663         Assert._assert(f.getType().isAddressType());
664         if (!jq.RunningNative) return (Address)Reflection.obj_trav.getInstanceFieldValue(o, f);
665         Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
666         return HeapAddress.addressOf(o).offset(f.getOffset()).peek();
667     }
668     public byte getfield_B(Object o, jq_InstanceField f) {
669         Assert._assert(f.getType() == jq_Primitive.BYTE);
670         if (!jq.RunningNative) {
671             Object q = Reflection.obj_trav.getInstanceFieldValue(o, f);
672             if (q == null) return 0;
673             return ((Byte)q).byteValue();
674         }
675         Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
676         return HeapAddress.addressOf(o).offset(f.getOffset()).peek1();
677     }
678     public char getfield_C(Object o, jq_InstanceField f) {
679         Assert._assert(f.getType() == jq_Primitive.CHAR);
680         if (!jq.RunningNative) {
681             Object q = Reflection.obj_trav.getInstanceFieldValue(o, f);
682             if (q == null) return 0;
683             return ((Character)q).charValue();
684         }
685         Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
686         return (char)HeapAddress.addressOf(o).offset(f.getOffset()).peek4();
687     }
688     public short getfield_S(Object o, jq_InstanceField f) {
689         Assert._assert(f.getType() == jq_Primitive.SHORT);
690         if (!jq.RunningNative) {
691             Object q = Reflection.obj_trav.getInstanceFieldValue(o, f);
692             if (q == null) return 0;
693             return ((Short)q).shortValue();
694         }
695         Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
696         return HeapAddress.addressOf(o).offset(f.getOffset()).peek2();
697     }
698     public boolean getfield_Z(Object o, jq_InstanceField f) {
699         Assert._assert(f.getType() == jq_Primitive.BOOLEAN);
700         if (!jq.RunningNative) {
701             Object q = Reflection.obj_trav.getInstanceFieldValue(o, f);
702             if (q == null) return false;
703             return ((Boolean)q).booleanValue();
704         }
705         Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
706         return HeapAddress.addressOf(o).offset(f.getOffset()).peek1()!=0;
707     }
708     public Object getfield(Object o, jq_InstanceField f) {
709         if (!jq.RunningNative) return Reflection.obj_trav.getInstanceFieldValue(o, f);
710         jq_Type t = f.getType();
711         if (t.isReferenceType()) return getfield_A(o, f);
712         if (t == jq_Primitive.INT) return new Integer(getfield_I(o, f));
713         if (t == jq_Primitive.FLOAT) return new Float(getfield_F(o, f));
714         if (t == jq_Primitive.LONG) return new Long(getfield_L(o, f));
715         if (t == jq_Primitive.DOUBLE) return new Double(getfield_D(o, f));
716         if (t == jq_Primitive.BYTE) return new Byte(getfield_B(o, f));
717         if (t == jq_Primitive.CHAR) return new Character(getfield_C(o, f));
718         if (t == jq_Primitive.SHORT) return new Short(getfield_S(o, f));
719         if (t == jq_Primitive.BOOLEAN) return Convert.getBoolean(getfield_Z(o, f));
720         Assert.UNREACHABLE();
721         return null;
722     }
723     public void putfield_I(Object o, jq_InstanceField f, int v) {
724         Assert._assert(f.getType() == jq_Primitive.INT || f.getType() == jq_Primitive.FLOAT);
725         if (!jq.RunningNative) {
726             Reflection.obj_trav.putInstanceFieldValue(o, f, new Integer(v));
727             return;
728         }
729         Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
730         HeapAddress.addressOf(o).offset(f.getOffset()).poke4(v);
731     }
732     public void putfield_L(Object o, jq_InstanceField f, long v) {
733         Assert._assert(f.getType() == jq_Primitive.LONG || f.getType() == jq_Primitive.DOUBLE);
734         if (!jq.RunningNative) {
735             Reflection.obj_trav.putInstanceFieldValue(o, f, new Long(v));
736             return;
737         }
738         Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
739         HeapAddress.addressOf(o).offset(f.getOffset()).poke8(v);
740     }
741     public void putfield_F(Object o, jq_InstanceField f, float v) {
742         Assert._assert(f.getType() == jq_Primitive.FLOAT);
743         if (!jq.RunningNative) {
744             Reflection.obj_trav.putInstanceFieldValue(o, f, new Float(v));
745             return;
746         }
747         Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
748         putfield_I(o, f, Float.floatToRawIntBits(v));
749     }
750     public void putfield_D(Object o, jq_InstanceField f, double v) {
751         Assert._assert(f.getType() == jq_Primitive.DOUBLE);
752         if (!jq.RunningNative) {
753             Reflection.obj_trav.putInstanceFieldValue(o, f, new Double(v));
754             return;
755         }
756         Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
757         putfield_L(o, f, Double.doubleToRawLongBits(v));
758     }
759     public void putfield_A(Object o, jq_InstanceField f, Object v) {
760         if (!jq.RunningNative) {
761             Reflection.obj_trav.putInstanceFieldValue(o, f, v);
762             return;
763         }
764         Assert._assert(v == null || TypeCheck.isAssignable(jq_Reference.getTypeOf(v), f.getType()));
765         Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
766         HeapAddress.addressOf(o).offset(f.getOffset()).poke(HeapAddress.addressOf(v));
767     }
768     public void putfield_P(Object o, jq_InstanceField f, Address v) {
769         Assert._assert(f.getType().isAddressType());
770         if (!jq.RunningNative) {
771             Reflection.obj_trav.putInstanceFieldValue(o, f, v);
772             return;
773         }
774         Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
775         HeapAddress.addressOf(o).offset(f.getOffset()).poke(v);
776     }
777     public void putfield_B(Object o, jq_InstanceField f, byte v) {
778         Assert._assert(f.getType() == jq_Primitive.BYTE);
779         if (!jq.RunningNative) {
780             Reflection.obj_trav.putInstanceFieldValue(o, f, new Byte(v));
781             return;
782         }
783         Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
784         HeapAddress.addressOf(o).offset(f.getOffset()).poke1(v);
785     }
786     public void putfield_C(Object o, jq_InstanceField f, char v) {
787         Assert._assert(f.getType() == jq_Primitive.CHAR);
788         if (!jq.RunningNative) {
789             Reflection.obj_trav.putInstanceFieldValue(o, f, new Character(v));
790             return;
791         }
792         Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
793         HeapAddress.addressOf(o).offset(f.getOffset()).poke2((short)((v<<16)>>16));
794     }
795     public void putfield_S(Object o, jq_InstanceField f, short v) {
796         Assert._assert(f.getType() == jq_Primitive.SHORT);
797         if (!jq.RunningNative) {
798             Reflection.obj_trav.putInstanceFieldValue(o, f, new Short(v));
799             return;
800         }
801         Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
802         HeapAddress.addressOf(o).offset(f.getOffset()).poke2(v);
803     }
804     public void putfield_Z(Object o, jq_InstanceField f, boolean v) {
805         Assert._assert(f.getType() == jq_Primitive.BOOLEAN);
806         if (!jq.RunningNative) {
807             Reflection.obj_trav.putInstanceFieldValue(o, f, Convert.getBoolean(v));
808             return;
809         }
810         Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
811         HeapAddress.addressOf(o).offset(f.getOffset()).poke1(v?(byte)1:(byte)0);
812     }
813     
814     public int getstatic_I(jq_StaticField f) {
815         Assert._assert(f.getType() == jq_Primitive.INT || f.getType() == jq_Primitive.FLOAT);
816         if (!jq.RunningNative) {
817             Object o = Reflection.obj_trav.getStaticFieldValue(f);
818             if (o == null) return 0;
819             return ((Integer)o).intValue();
820         }
821         return f.getAddress().peek4();
822     }
823     public long getstatic_L(jq_StaticField f) {
824         Assert._assert(f.getType() == jq_Primitive.LONG || f.getType() == jq_Primitive.DOUBLE);
825         if (!jq.RunningNative) {
826             Object o = Reflection.obj_trav.getStaticFieldValue(f);
827             if (o == null) return 0L;
828             return ((Long)o).longValue();
829         }
830         return f.getAddress().peek8();
831     }
832     public float getstatic_F(jq_StaticField f) {
833         Assert._assert(f.getType() == jq_Primitive.FLOAT);
834         if (!jq.RunningNative) {
835             Object o = Reflection.obj_trav.getStaticFieldValue(f);
836             if (o == null) return 0L;
837             return ((Float)o).floatValue();
838         }
839         return Float.intBitsToFloat(getstatic_I(f));
840     }
841     public double getstatic_D(jq_StaticField f) {
842         Assert._assert(f.getType() == jq_Primitive.DOUBLE);
843         if (!jq.RunningNative) {
844             Object o = Reflection.obj_trav.getStaticFieldValue(f);
845             if (o == null) return 0L;
846             return ((Double)o).doubleValue();
847         }
848         return Double.longBitsToDouble(getstatic_L(f));
849     }
850     public Object getstatic_A(jq_StaticField f) {
851         Assert._assert(f.getType().isReferenceType() && !f.getType().isAddressType());
852         if (!jq.RunningNative) return Reflection.obj_trav.getStaticFieldValue(f);
853         return ((HeapAddress) f.getAddress().peek()).asObject();
854     }
855     public Address getstatic_P(jq_StaticField f) {
856         Assert._assert(f.getType().isAddressType());
857         if (!jq.RunningNative) {
858             Address a = (Address)Reflection.obj_trav.getStaticFieldValue(f);
859             //if (a == null) return HeapAddress.getNull();
860             return a;
861         }
862         return f.getAddress().peek();
863     }
864     public boolean getstatic_Z(jq_StaticField f) {
865         Assert._assert(f.getType() == jq_Primitive.BOOLEAN);
866         if (!jq.RunningNative) {
867             Object o = Reflection.obj_trav.getStaticFieldValue(f);
868             if (o == null) return false;
869             return ((Boolean)o).booleanValue();
870         }
871         return f.getAddress().peek4()!=0;
872     }
873     public byte getstatic_B(jq_StaticField f) {
874         Assert._assert(f.getType() == jq_Primitive.BYTE);
875         if (!jq.RunningNative) {
876             Object o = Reflection.obj_trav.getStaticFieldValue(f);
877             if (o == null) return 0;
878             return ((Byte)o).byteValue();
879         }
880         return f.getAddress().peek1();
881     }
882     public short getstatic_S(jq_StaticField f) {
883         Assert._assert(f.getType() == jq_Primitive.SHORT);
884         if (!jq.RunningNative) {
885             Object o = Reflection.obj_trav.getStaticFieldValue(f);
886             if (o == null) return 0;
887             return ((Short)o).shortValue();
888         }
889         return f.getAddress().peek2();
890     }
891     public char getstatic_C(jq_StaticField f) {
892         Assert._assert(f.getType() == jq_Primitive.CHAR);
893         if (!jq.RunningNative) {
894             Object o = Reflection.obj_trav.getStaticFieldValue(f);
895             if (o == null) return 0;
896             return ((Character)o).charValue();
897         }
898         return (char)f.getAddress().peek4();
899     }
900     public void putstatic_I(jq_StaticField f, int v) {
901         Assert._assert(f.getType() == jq_Primitive.INT);
902         if (!jq.RunningNative) {
903             Reflection.obj_trav.putStaticFieldValue(f, new Integer(v));
904             return;
905         }
906         f.getDeclaringClass().setStaticData(f, v);
907     }
908     public void putstatic_L(jq_StaticField f, long v) {
909         Assert._assert(f.getType() == jq_Primitive.LONG);
910         if (!jq.RunningNative) {
911             Reflection.obj_trav.putStaticFieldValue(f, new Long(v));
912             return;
913         }
914         f.getDeclaringClass().setStaticData(f, v);
915     }
916     public void putstatic_F(jq_StaticField f, float v) {
917         Assert._assert(f.getType() == jq_Primitive.FLOAT);
918         if (!jq.RunningNative) {
919             Reflection.obj_trav.putStaticFieldValue(f, new Float(v));
920             return;
921         }
922         f.getDeclaringClass().setStaticData(f, v);
923     }
924     public void putstatic_D(jq_StaticField f, double v) {
925         Assert._assert(f.getType() == jq_Primitive.DOUBLE);
926         if (!jq.RunningNative) {
927             Reflection.obj_trav.putStaticFieldValue(f, new Double(v));
928             return;
929         }
930         f.getDeclaringClass().setStaticData(f, v);
931     }
932     public void putstatic_A(jq_StaticField f, Object v) {
933         Assert._assert(v == null || TypeCheck.isAssignable(jq_Reference.getTypeOf(v), f.getType()));
934         Assert._assert(!f.getType().isAddressType());
935         if (!jq.RunningNative) {
936             Reflection.obj_trav.putStaticFieldValue(f, v);
937             return;
938         }
939         f.getDeclaringClass().setStaticData(f, v);
940     }
941     public void putstatic_P(jq_StaticField f, Address v) {
942         Assert._assert(f.getType().isAddressType());
943         if (!jq.RunningNative) {
944             Reflection.obj_trav.putStaticFieldValue(f, v);
945             return;
946         }
947         f.getDeclaringClass().setStaticData(f, v);
948     }
949     public void putstatic_Z(jq_StaticField f, boolean v) {
950         Assert._assert(f.getType() == jq_Primitive.BOOLEAN);
951         if (!jq.RunningNative) {
952             Reflection.obj_trav.putStaticFieldValue(f, Convert.getBoolean(v));
953             return;
954         }
955         f.getDeclaringClass().setStaticData(f, v?1:0);
956     }
957     public void putstatic_B(jq_StaticField f, byte v) {
958         Assert._assert(f.getType() == jq_Primitive.BYTE);
959         if (!jq.RunningNative) {
960             Reflection.obj_trav.putStaticFieldValue(f, new Byte(v));
961             return;
962         }
963         f.getDeclaringClass().setStaticData(f, (int)v);
964     }
965     public void putstatic_S(jq_StaticField f, short v) {
966         Assert._assert(f.getType() == jq_Primitive.SHORT);
967         if (!jq.RunningNative) {
968             Reflection.obj_trav.putStaticFieldValue(f, new Short(v));
969             return;
970         }
971         f.getDeclaringClass().setStaticData(f, (int)v);
972     }
973     public void putstatic_C(jq_StaticField f, char v) {
974         Assert._assert(f.getType() == jq_Primitive.CHAR);
975         if (!jq.RunningNative) {
976             Reflection.obj_trav.putStaticFieldValue(f, new Character(v));
977             return;
978         }
979         f.getDeclaringClass().setStaticData(f, (int)v);
980     }
981     
982     public int arraylength(Object o) {
983         Assert._assert(getTypeOf(o).isArrayType());
984         if (!jq.RunningNative) return Array.getLength(o);
985         return HeapAddress.addressOf(o).offset(joeq.Allocator.ObjectLayout.ARRAY_LENGTH_OFFSET).peek4();
986     }
987     public Object arrayload_A(Object[] o, int i) {
988         if (!jq.RunningNative) return Reflection.obj_trav.mapValue(o[i]);
989         return o[i];
990     }
991     public Address arrayload_R(Address[] o, int i) {
992         return o[i];
993     }
994 
995     public void registerNullStaticFields(Set s) {
996         s.add(_declaredFieldsCache);
997         s.add(_declaredMethodsCache);
998     }
999 
1000     public void initialize() {
1001         _class = (jq_Class)PrimordialClassLoader.loader.getOrCreateBSType("Ljoeq/Runtime/ReflectionImpl;");
1002         _declaredFieldsCache = _class.getOrCreateStaticField("declaredFieldsCache", "Ljava/util/HashMap;");
1003         _declaredMethodsCache = _class.getOrCreateStaticField("declaredMethodsCache", "Ljava/util/HashMap;");
1004     }
1005     
1006     public static jq_Class _class;
1007     public static jq_StaticField _declaredFieldsCache;
1008     public static jq_StaticField _declaredMethodsCache;
1009 }